home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-27 | 14.2 KB | 461 lines | [TEXT/YHS2] |
- -- Peter Henderson's Recursive Geometry
- -- Syam Gadde and Bo Whong
- -- full set of modules
- -- CS429 Project
- -- 4/30/93
-
- module HendersonLib (Hostname(..), Filename(..), VTriple(..), HendQuartet(..),
- Picture(..), sendToDraw, draw, create, modify, plot) where
- import Xlib
-
- -- ADTs and Type Synonyms --------------------------------------------------
- data Picture = Nil
- | Flip Picture
- | Beside Float Picture Float Picture
- | Above Float Picture Float Picture
- | Rot Picture
- | File String
- | Overlay Picture Picture
- | Grid Int Int SegList
- deriving Text
-
- data Plot = Plot Picture VTriple
- | Union Plot Plot
-
- type Hostname = String
- type Filename = String
- type IntPoint = (Int,Int)
- type IntSegment = (IntPoint, IntPoint)
- type IntSegList = [IntSegment]
- type Point = (Float,Float)
- type Segment = (Point, Point)
- type SegList = [Segment]
- type Vector = Point
- type VTriple = (Vector, Vector, Vector)
- type HendQuartet = (Int, Int, Int, Int)
- type PEnv = [(Filename, Picture)]
-
- -- vector Functions --------------------------------------------------------
- -- for adding, negating, multiplying, and dividing vectors
-
- addV :: Vector -> Vector -> Vector
- addV (x1,y1) (x2,y2) = (x1+x2, y1+y2)
-
- negateV :: Vector -> Vector
- negateV (x,y) = (-x,-y)
-
- multV :: Float-> Vector -> Vector
- multV a (x,y) = (a*x, a*y)
-
- divV :: Float -> Vector -> Vector
- divV a (x,y) = (x/a, y/a)
-
- -- plot Function -----------------------------------------------------------
- -- picture manipulation function
-
- plot :: Picture -> VTriple -> PEnv -> ((Plot, PEnv) -> IO()) -> IO()
-
- -- the Nil Picture is just "nothingness" so choose an abritrary representation
- -- of nothingness.
- plot Nil (v1, v2, v3) env cont =
- plot (Grid 1 1 []) (v1,v2,v3) env cont
-
- -- Flipping a Picture
- plot (Flip p1) (v1, v2, v3) env cont =
- plot p1 (addV v1 v2, negateV v2, v3) env cont
-
- -- Rotate a Picture 90 degrees counterclockwise
- plot (Rot p1) (v1, v2, v3) env cont =
- plot p1 (addV v1 v3, negateV v3, v2) env cont
-
- -- Overlay one Picture over another Picture
- plot (Overlay p q) (a,b,c) env cont =
- plot p (a,b,c) env $ \ (plot1, env1) ->
- plot q (a,b,c) env1 $ \ (plot2, env2) ->
- cont ((Union plot1 plot2), env2)
-
- -- Place p1 Beside p2 with width ratio m to n
- plot (Beside m p1 n p2) (v1, v2, v3) env cont =
- plot p1 (v1, multV (m/(m+n)) v2, v3) env $ \ (plot1, env1) ->
- plot p2 ((addV (multV (m/(m+n)) v2) v1),
- (multV (n/(m+n)) v2),
- v3) env1 $ \ (plot2, env2) ->
- cont ((Union plot1 plot2), env2)
-
- -- Place p Above q with height ratio m to n
- plot (Above m p n q) (a,b,c) env cont =
- plot q (addV a (multV (m/(n+m)) c), b, multV (n/(m+n)) c) env
- $ \ (plot1, env1) ->
- plot p (a, b, multV (m/(m+n)) c) env1 $ \ (plot2, env2) ->
- cont ((Union plot1 plot2), env2)
-
- -- the 'real' Picture
- plot (Grid x y s) (a,b,c) env cont =
- cont ((Plot (Grid x y s) (a,b,c)), env)
-
- -- this picture is located in a File with name name
- -- lookup table: thanks to Sheng
- plot (File name) (a,b,c) env cont =
- case (lookupEnv env name) of
- ((_, pic):_) -> plot pic (a,b,c) env cont
- [] ->
- readFile name >>= \s ->
- let
- pic = read s
- newenv = (name,pic):env
- in
- plot pic (a,b,c) newenv cont
-
- lookupEnv :: PEnv -> Filename -> PEnv
- lookupEnv [] _ = []
- lookupEnv ((a,b):es) name | a==name = ((a,b):es)
- | otherwise = lookupEnv es name
-
- -- Draw Function -----------------------------------------------------------
- -- user function to draw pictures
-
- draw :: Hostname -> Picture -> VTriple -> HendQuartet -> IO()
-
- -- opens a display, screen, and window (of size specified in HendQuartet)
- -- and draws Picture in the window
- draw host p (a,b,c) (hm,hn,ho,hp) =
- xOpenDisplay host >>= \display -> -- opens display
- let (screen:_) = xDisplayRoots display
- fg_color = xScreenBlackPixel screen
- bg_color = xScreenWhitePixel screen
- root = xScreenRoot screen
- in
- xCreateWindow root -- opens window
- (XRect hm hn ho hp)
- [XWinBackground bg_color,
- XWinEventMask (XEventMask [XKeyPress,
- XExposure,
- XButtonPress])]
- >>= \window ->
- xSetWmName window "Henderson Graphics" >>
- xSetWmIconName window "Henderson Graphics" >>
- xMapWindow window >> -- show window
- xDisplayForceOutput display >> -- show window NOW
- xCreateGcontext (XDrawWindow (xScreenRoot screen)) -- open a GC
- [XGCBackground bg_color,
- XGCForeground fg_color] >>= \ gcontext ->
- plot p (a,b,c) [] $ \(plt,_) -> -- make pic easier to work with
- let
- handleEvent =
- xGetEvent display >>= \event ->
- case (xEventType event) of
- -- Has a part of the window been uncovered?
- XExposureEvent -> sendToDraw window screen display gcontext plt
- >> handleEvent
- _ -> xCloseDisplay display
- in
- handleEvent
-
- -- SendToDraw Function -----------------------------------------------------
- -- called by draw to actually draw the lines onto the window
-
- sendToDraw :: XWindow -> XScreen -> XDisplay -> XGcontext -> Plot -> IO()
-
- -- have a Union. so do one, and then the other. simple.
- sendToDraw win screen display gcontext (Union p1 p2) =
- sendToDraw win screen display gcontext p1 >>
- sendToDraw win screen display gcontext p2
-
- -- have just a Plot. have to do some dirty work.
- sendToDraw window screen display gcontext (Plot (Grid x y s) (a,b,c)) =
- let
- v2p :: Vector -> XPoint
- v2p (e,f) = XPoint (round e) (round f) -- convert Vector to an XPoint
- fx :: Float
- fx = fromIntegral x
- fy :: Float
- fy = fromIntegral y
- drawit :: SegList -> IO()
- -- draw the Grid one line at a time
- drawit [] = return()
- drawit (((x0,y0),(x1,y1)):ss) =
- xDrawLine (XDrawWindow window)
- gcontext
- (v2p (addV (addV a (multV (x0/fx) b))
- (multV (y0/fy) c)))
- (v2p (addV (addV a (multV (x1/fx) b))
- (multV (y1/fy) c))) >>
- drawit ss
- in
- drawit s >>
- xDisplayForceOutput display
-
- -- create function ---------------------------------------------------------
- -- opens up a window to allow the user to create a file
- -- and save it onto a file
-
- create :: Hostname -> Filename -> Int -> Int -> IO()
-
- create host filename x y =
- xOpenDisplay host >>= \ display ->
- let
- (screen:_) = xDisplayRoots display
- fg_color = xScreenWhitePixel screen
- bg_color = xScreenBlackPixel screen
- root = xScreenRoot screen
- in
- xCreateWindow root
- (XRect 0 0 (x+1) (y+1))
- [XWinBackground bg_color,
- XWinEventMask (XEventMask [XExposure,
- XKeyPress,
- XButtonPress,
- XPointerMotion])]
- >>= \window ->
- xSetWmName window filename >>
- xSetWmIconName window filename >>
- xCreateWindow root
- (XRect 0 0 100 40)
- [XWinBackground bg_color] >>= \window2 ->
- xSetWmName window2 "pos" >>
- xSetWmIconName window2 "pos" >>
- xMapWindow window >>
- xMapWindow window2 >>
- xListFonts display "*times*bold*r*normal*18*" >>= \fontlist ->
- xCreateGcontext (XDrawWindow root)
- [XGCBackground bg_color,
- XGCForeground fg_color,
- XGCFont (head fontlist)] >>= \gcontext ->
- let
- handleEvent :: IntSegList -> IO()
- handleEvent list =
- xGetEvent display >>= \event ->
- let
- point = xEventPos event
- XPoint pointx pointy = point
- handleEvent' :: XPoint -> IO()
- handleEvent' last =
- xGetEvent display >>= \event2 ->
- let
- pos = xEventPos event2
- XPoint posx posy = pos
- in
- case (xEventType event2) of
- XKeyPressEvent ->
- putStr ((show (tup pos))++ "\n") >>
- xDrawLine (XDrawWindow window) gcontext point pos
- >> handleEvent (store list point pos)
- XExposureEvent ->
- redraw window gcontext list >> handleEvent' last
- XMotionNotifyEvent ->
- xDrawImageGlyphs (XDrawWindow window2)
- gcontext
- (XPoint 2 18)
- ((show posx)++", "++(show posy)++" ")
- >> handleEvent' last
- _ ->
- handleEvent' last
- in
- case (xEventType event) of
- XButtonPressEvent ->
- putFile display filename list x y "create"
- XKeyPressEvent ->
- putStr (show (tup point)) >>
- handleEvent' point
- XExposureEvent ->
- redraw window gcontext list >> handleEvent list
- XMotionNotifyEvent ->
- xDrawImageGlyphs (XDrawWindow window2)
- gcontext
- (XPoint 2 18)
- ((show pointx)++", "++(show pointy)++" ")
- >> handleEvent list
- _ ->
- handleEvent list
- in
- case (checkFile filename) of
- True -> handleEvent []
- False -> putStr picTypeError >>
- xCloseDisplay display
-
- -- modify function ---------------------------------------------------------
- -- allows the user to add onto an already existing picture file
-
- modify :: Hostname -> Filename -> IO()
-
- modify host filename =
- case (checkFile filename) of
- False -> putStr picTypeError
- True ->
- readFile filename >>= \s ->
- let
- dat = read s
- origlist = fFloat (getlist dat)
- x = getx dat
- y = gety dat
- in
- xOpenDisplay host >>= \ display ->
- let
- (screen:_) = xDisplayRoots display
- fg_color = xScreenWhitePixel screen
- bg_color = xScreenBlackPixel screen
- root = xScreenRoot screen
- in
- xCreateWindow root
- (XRect 0 0 (x + 1) (y + 1))
- [XWinBackground bg_color,
- XWinEventMask (XEventMask [XExposure, XKeyPress,
- XButtonPress, XPointerMotion])]
- >>= \window ->
- xSetWmName window filename >>
- xSetWmIconName window filename >>
- xCreateWindow root (XRect 0 0 100 40)
- [XWinBackground bg_color] >>= \window2 ->
- xSetWmName window2 "pos" >>
- xSetWmIconName window2 "pos" >>
- xMapWindow window >>
- xMapWindow window2 >>
- xListFonts display "*times*bold*r*normal*18*" >>= \fontlist ->
- xCreateGcontext (XDrawWindow root) [XGCBackground bg_color,
- XGCForeground fg_color,
- XGCFont (head fontlist)]
- >>= \ gcontext ->
- let
- handleEvent :: IntSegList -> IO()
- handleEvent list =
- xGetEvent display >>= \event ->
- let
- point = xEventPos event
- XPoint pointx pointy = point
- handleEvent' :: XPoint -> IO()
- handleEvent' last = xGetEvent display >>= \event2 ->
- let
- pos = xEventPos event2
- XPoint posx posy = pos
- in
- case (xEventType event2) of
- XExposureEvent ->
- redraw window gcontext list >>
- handleEvent' last
- XKeyPressEvent ->
- putStr ((show (tup pos))++ "\n") >>
- xDrawLine (XDrawWindow window) gcontext point pos
- >> handleEvent (store list point pos)
- XMotionNotifyEvent ->
- xDrawImageGlyphs (XDrawWindow window2) gcontext
- (XPoint 2 18) ((show posx)++", "++(show posy)++" ")
- >> handleEvent' last
- _ -> handleEvent' last
- in
- case (xEventType event) of
- XButtonPressEvent ->
- putFile display filename list x y "modify"
- XKeyPressEvent ->
- putStr (show (tup point)) >>
- handleEvent' point
- XExposureEvent ->
- redraw window gcontext list >>
- handleEvent list
- XMotionNotifyEvent ->
- xDrawImageGlyphs (XDrawWindow window2)
- gcontext (XPoint 2 18)
- ((show pointx)++", "++(show pointy)++" ")
- >> handleEvent list
- _ ->
- handleEvent list
- in
- redraw window gcontext origlist >>
- handleEvent origlist
-
- -- Miscellaneous functions -------------------------------------------------
- -- shared by the create and modify functions
-
- checkFile :: Filename -> Bool
- checkFile name =
- case (take 4 (reverse name)) of
- "cip." -> True
- _ -> False
-
- store :: IntSegList -> XPoint -> XPoint -> IntSegList
- store l a b = [((xof a,yof a),(xof b,yof b))] ++ l
-
- xof :: XPoint -> Int
- xof (XPoint x y) = x
-
- yof :: XPoint -> Int
- yof (XPoint x y) = y
-
- tup :: XPoint -> IntPoint
- tup (XPoint a b) = (a,b)
-
- ll:: IntSegment -> Int
- ll ((a1,a2),(b1,b2)) = a1
-
- lr:: IntSegment -> Int
- lr ((a1,a2),(b1,b2)) = a2
-
- rl:: IntSegment -> Int
- rl ((a1,a2),(b1,b2)) = b1
-
- rr:: IntSegment -> Int
- rr ((a1,a2),(b1,b2)) = b2
-
- getx :: Picture -> Int
- getx (Grid m n o) = m
-
- gety :: Picture -> Int
- gety(Grid m n o) = n
-
- getlist :: Picture -> SegList
- getlist (Grid m n o) = o
-
- fFloat :: SegList -> IntSegList
- fFloat = map (\ ((ix,iy),(jx,jy)) ->
- ((round ix,round iy), (round jx,round jy)))
-
- readError :: String
- readError = "Error: reading an invalid file\n"
-
- picTypeError :: String
- picTypeError = "Error: files need to be of .pic type\n"
-
- deleteError :: String
- deleteError = "Error: file can not be deleted\n"
-
- writeError :: String
- writeError = "Error: file can not be written\n"
-
- modError :: String
- modError = "Error: file can not be modified\n"
-
- redraw :: XWindow-> XGcontext -> IntSegList -> IO()
- redraw window gcontext [] = return ()
- redraw window gcontext (l:ls) =
- xDrawLine (XDrawWindow window) gcontext (XPoint (ll l) (lr l))
- (XPoint (rl l) (rr l))
- >> redraw window gcontext ls
-
- changeList :: IntSegList -> SegList
- changeList =
- map (\ ((ix,iy),(jx,jy)) -> ((fromIntegral ix,fromIntegral iy),
- (fromIntegral jx,fromIntegral jy)))
-
- putFile :: XDisplay -> Filename -> IntSegList ->
- Int -> Int -> String -> IO()
- putFile display name list x y flag =
- let
- text = show (Grid x y (changeList list))
- finishMsg = name ++ ": Done...Process completed\n"
- modMsg = name ++ ": Modifying file\n"
- createMsg = name ++ ": Creating file\n"
- continue =
- deleteFile name >>
- writeFile name text >>
- putStr finishMsg >>
- xCloseDisplay display
- in
- case (flag == "create") of
- False -> putStr modMsg >>
- continue
- True -> (try (readFile name >> continue)
- (\e -> putStr createMsg >>
- writeFile name text >>
- (xCloseDisplay display)))
-
-
-